package cpa.prowon.image;

import java.io.File;
import java.util.Iterator;
import java.util.Observable;

import pho.prowon.ImageData;
import pho.prowon.ImageDataContainer;
import pho.prowon.jpeg.JpegWriter;

/**
 * The image container holds several information about an image, from
 * the image data (IPTC information), file path, the image itself etc.
 * @author Chris
 */
public class ImageContainer extends Observable implements ImageDataContainer
{
	
	// Properties
	private String pathName = "";
	private ImageData imageData;
	
	/**
	 * Constructor
	 * @author Chris
	 */
	public ImageContainer() {
		super();
	}

	/**
	 * Constructor
	 * @param File The file path where the image can be found
	 * @author Chris
	 */
	public ImageContainer(File filePath) {
		
		// Set the image data
		imageData = new ImageData(filePath);
		
		// Set the path name
		pathName = imageData.getPathName();
		
	}
	
	/**
	 * Return whether or not the image is valid (for non jpeg files)
	 * @return True if the imgage is a real jpg file and valid, false otherwise
	 * @author Chris
	 */
	public boolean isValid() {
		return imageData.isValid();
	}
	
	/**
	 * Return whether or not the specified tag is an image data tag array
	 * @param String The tag name
	 * @return True if the tag is an array, false if not
	 * @author Chris
	 */
	public boolean isImageDataTagArray(String tag) {
		return imageData.isImageDataTagArray(tag);
	}
	
	/**
	 * Return a meaningful name/identifier for the image
	 * @return A meaningful name/identifier for the image
	 * @author Chris
	 */
	public String toString() {
		return getPathName();
	}

	/**
	 * Return whether or not the image container has been changed
	 * @return True if the image container has been changed, false otherwise
	 * @author Chris
	 */
	public boolean hasChanged() {
		return imageData.hasChanged();
	}

	/**
	 * Return whether or not the image container equals another one. The unique
	 * key for an image container is the path
	 * @param Object The object to compare with
	 * @author Chris
	 */
	public boolean equals(Object obj) {

		if (obj == null || ! (obj instanceof ImageContainer)) {
			return false;
		}
		return getPathName().equals(((ImageContainer)obj).getPathName());

	}
	
	/**
	 * Set the image data information (IPTC information object)
	 * @param ImageData The image data object which holds the IPTC information for this image
	 * @author Chris
	 */
	public void setImageData(ImageData imd)	{
		imageData = imd;
		pathName = imageData.getPathName();
		
		if (hasChanged())
		{
			setChanged ();
			notifyObservers();
		}
	}

	/**
	 * Get the image data information (IPTC information object)
	 * @return ImageData The image data object which holds the IPTC information for this image
	 * @author Chris
	 */
	public ImageData getImageData()	{
		return imageData;
	}

	/**
	 * Get a specified image data tag value
	 * @param String The tag name
	 * @return String The value for the specified tag
	 * @author Chris
	 */
	public String getImageDataTag(String tagName) {
		return getImageData().getImageDataTag(tagName);
	}
	
	/**
	 * Set an image data tag to a specified value
	 * @param String The tag name
	 * @param String the tag value
	 * @author Chris
	 */
	public void setImageDataTag(String tagName, String value) {
		getImageData().setImageDataTag(tagName, value);
		
		if (hasChanged())
		{
			setChanged ();
			notifyObservers();
		}
	}

	/**
	 * Get the specified image data tag values
	 * @param String The tag name
	 * @return String[] The values for the specified tag
	 * @author Chris
	 */
	public String[] getImageDataTagArray(String tagName) {
		return getImageData().getImageDataTagArray(tagName);
	}
	
	/**
	 * Set the image data tag values
	 * @param String The tag name
	 * @param String[] The tag values
	 * @author Chris
	 */
	public void setImageDataTagArray(String tagName, String[] values) {
		getImageData().setImageDataTagArray(tagName, values);

		if (hasChanged())
		{
			setChanged ();
			notifyObservers();
		}
	}
	
	/**
	 * Get the path to the image
	 * @return String The path to the image
	 * @author Chris
	 */
	public String getPathName() {
		return pathName;
	}
	
	/**
	 * Get the file name only of the image
	 * @return The file name of the image
	 * @author Chris
	 */
	public String getFileName() {
		File path = new File(this.getImageData().getPathName());
		return path.getName();
	}
	
	/**
	 * Return an abbreviated path to the image
	 * @return An abbreviated path
	 * @author Chris
	 */
	public String getAbbreviatedPathName() {
		return getAbbreviatedPathName(40);
	}
	
	/**
	 * Return an abbreviated path to the image
	 * @param int The maximum length of the path
	 * @return An abbreviated path
	 * @author Chris
	 */
	public String getAbbreviatedPathName(int maxLength) {
		
		String abbPath = getPathName();
		if (abbPath.length() > maxLength)
			{
				int driveNameLen = abbPath.indexOf(File.separator);
				abbPath = abbPath.substring(0, driveNameLen+1) + "..." + abbPath.substring(abbPath.length()-maxLength+driveNameLen+3);
			}
		return abbPath;
	}
	
	/**
	 * Get the iterator that can be used to iterate through the IPTC tags
	 * @return Iterator The iterator to the tag names
	 * @author Chris
	 */
	public Iterator getTagNameIterator() {
		return getImageData().getTagNameIterator();
	}
	
	/**
	 * Get the title of the image
	 * @return String The title of the image
	 * @author Chris
	 */
	public String getTitle() {
		return getImageDataTag("Headline");
	}

	/**
	 * Get the creation date of the image
	 * @return String The creation date of the image. The format of the image is specified in the
	 * application properties prowon.DateFormat
	 * @author Chris
	 */
	public String getDate() {
		return getImageDataTag("DateCreated");
	}

	/**
	 * Get the description of the image
	 * @return String The description of the image
	 * @author Chris
	 */
	public String getDescription() {
		return getImageDataTag("CaptionAbstract");
	}

	/**
	 * Get the gallery the image is assigned to
	 * @return String The gallery the image is assigned to
	 * @author Chris
	 */
	public String getGallery() {
		return getImageDataTag("Source");
	}

	/**
	 * Get the city where the image was taken
	 * @return String The city where the image was taken
	 * @author Chris
	 */
	public String getCity() {
		return getImageDataTag("City");
	}

	/**
	 * Get the province/state where the image was taken
	 * @return String The province/state where the image was taken
	 * @author Chris
	 */
	public String getProvinceState() {
		return getImageDataTag("ProvinceState");
	}

	/**
	 * Get the country where the image was taken
	 * @return String The country where the image was taken
	 * @author Chris
	 */
	public String getCountry() {
		return getImageDataTag("CountryPrimaryLocation");
	}

	/**
	 * Get the cateogry of the image
	 * @return String The category of the image
	 * @author Chris
	 */
	public String getCategory() {
		return getImageDataTag("Category");
	}

	/**
	 * Get the copyright of the image
	 * @return String The copyright of the image
	 * @author Chris
	 */
	public String getCopyright() {
		return getImageDataTag("CopyrightNotice");
	}

	/**
	 * Get the originating program of the image
	 * @return String The originating program of the image
	 * @author Chris
	 */
	public String getOriginatingProgram() {
		return getImageDataTag("OriginatingProgram");
	}

	/**
	 * Get the keywords of the image
	 * @return String[] The keywords of the image
	 * @author Chris
	 */
	public String[] getKeywords() {
		return getImageDataTagArray("Keywords");	
	}
	
	/**
	 * Get the supplemental categories of the image
	 * @return String[] The supplemental categories of the image
	 * @author Chris
	 */
	public String[] getSupplementalCategories() {
		return getImageDataTagArray("SupplementalCategorys");	
	}
	
	/**
	 * Set the title of the image
	 * @param String The title of the image
	 * @author Chris
	 */
	public void setTitle(String newValue) {
		setImageDataTag("Headline", newValue);
	}

	/**
	 * Set the creation date of the image
	 * @param String The creation date of the image. It has to be specified in the
	 * correct format which is specified via the application property prowon.DateFormat
	 * @author Chris
	 */
	public void setDate(String newValue) {
		setImageDataTag("DateCreated", newValue);
	}

	/**
	 * Set the description of the image
	 * @param String The description of the image
	 * @author Chris
	 */
	public void setDescription(String newValue) {
		setImageDataTag("CaptionAbstract", newValue);
	}

	/**
	 * Set the gallery of the image
	 * @param String The gallery of the image
	 * @author Chris
	 */
	public void setGallery(String newValue) {
		setImageDataTag("Source", newValue);
	}

	/**
	 * Set the city of the image
	 * @param String The city of the image
	 * @author Chris
	 */
	public void setCity(String newValue) {
		setImageDataTag("City", newValue);
	}

	/**
	 * Set the province/state of the image
	 * @param String The province/state of the image
	 * @author Chris
	 */
	public void setProvinceState(String newValue) {
		setImageDataTag("ProvinceState", newValue);
	}

	/**
	 * Set the country of the image
	 * @param String The country of the image
	 * @author Chris
	 */
	public void setCountry(String newValue) {
		setImageDataTag("CountryPrimaryLocation", newValue);
	}

	/**
	 * Set the category of the image
	 * @param String The category of the image
	 * @author Chris
	 */
	public void setCategory(String newValue) {
		setImageDataTag("Category", newValue);
	}

	/**
	 * Set the copyright of the image
	 * @param String The copyright of the image
	 * @author Chris
	 */
	public void setCopyright(String newValue) {
		setImageDataTag("CopyrightNotice", newValue);
	}

	/**
	 * Set the originating program of the image
	 * @param String The originating program of the image
	 * @author Chris
	 */
	public void setOriginatingProgram(String newValue) {
		setImageDataTag("OriginatingProgram", newValue);
	}

	/**
	 * Set the keywords of the image
	 * @param String The keywords of the image
	 * @author Chris
	 */
	public void setKeywords(String[] newValues) {
		setImageDataTagArray("Keywords", newValues);
	}
	
	/**
	 * Set the supplemental categories of the image
	 * @param String The supplemental categories of the image
	 * @author Chris
	 */
	public void setSupplementalCategories(String[] newValues) {
		setImageDataTagArray("SupplementalCategorys", newValues);
	}
	
	/**
	 * Save the image with a specified file name
	 * @param String The file name
	 * @author Chris
	 */
	public void saveAs(String fileName)
	{
		
		// Save the image
		JpegWriter jw = new JpegWriter(this);
		try {
			jw.writeJpegFile(fileName);
		} catch (Exception e) {
			System.out.println(e);
		}
		
		// Reset the changed flag on the image data
		imageData.setInitialized();
		
	}

	/**
	 * Save the image
	 * @author Chris
	 */
	public void save() {
		saveAs(getPathName());
	}
	
	public boolean canBeChanged ()
	{
		return new File (pathName).canWrite();
	}
	
}
